package com.teacher.game.framework.util;

import android.graphics.Rect;
import com.teacher.game.model.Block;
import com.teacher.game.model.Player;
import com.teacher.game.model.PowerUp;
import com.teacher.game.model.AbstractObstacle;
import java.util.ArrayList;

/**
 * 碰撞检测管理器
 * 负责游戏中所有的碰撞检测逻辑，包括精确碰撞和容错处理
 */
public class CollisionManager {
    
    // 容错边距 - 提供更好的游戏体验
    private static final int COLLISION_MARGIN = 8;
    
    /**
     * 检测两个矩形是否相交
     * @param rect1 矩形1
     * @param rect2 矩形2
     * @return 是否发生碰撞
     */
    public static boolean checkRectCollision(Rect rect1, Rect rect2) {
        return Rect.intersects(rect1, rect2);
    }
    
    /**
     * 检测玩家与障碍物的碰撞
     * @param player 玩家对象
     * @param blocks 障碍物列表
     * @return 发生碰撞的障碍物，如果没有碰撞返回null
     */
    public static Block checkPlayerBlockCollision(Player player, ArrayList<Block> blocks) {
        Rect playerRect = player.getCollisionRect();
        
        for (Block block : blocks) {
            Rect blockRect = block.getCollisionRect();
            
            // 使用精确碰撞检测提供更好的游戏体验
            if (checkPreciseCollision(player, block)) {
                return block; // 返回碰撞的障碍物
            }
        }
        
        return null; // 没有碰撞
    }
    
    /**
     * 检测玩家是否成功越过障碍物 (用于计分)
     * @param player 玩家对象
     * @param block 障碍物对象
     * @return 是否成功越过
     */
    public static boolean checkPlayerPassedBlock(Player player, Block block) {
        // 玩家的X坐标超过障碍物右边缘
        return player.getX() > block.getX() + block.getWidth();
    }
    
    /**
     * 精确碰撞检测 - 考虑容错边距，提供更好的游戏体验
     * @param player 玩家对象
     * @param block 障碍物对象
     * @return 是否发生精确碰撞
     */
    public static boolean checkPreciseCollision(Player player, Block block) {
        Rect playerRect = player.getCollisionRect();
        Rect blockRect = block.getCollisionRect();
        
        // 首先进行矩形碰撞检测
        if (!checkRectCollision(playerRect, blockRect)) {
            return false;
        }
        
        // 缩小碰撞盒，提供容错边距
        Rect precisePlayerRect = new Rect(
            playerRect.left + COLLISION_MARGIN,
            playerRect.top + COLLISION_MARGIN,
            playerRect.right - COLLISION_MARGIN,
            playerRect.bottom - COLLISION_MARGIN
        );
        
        Rect preciseBlockRect = new Rect(
            blockRect.left + COLLISION_MARGIN,
            blockRect.top + COLLISION_MARGIN,
            blockRect.right - COLLISION_MARGIN,
            blockRect.bottom - COLLISION_MARGIN
        );
        
        return checkRectCollision(precisePlayerRect, preciseBlockRect);
    }
    
    /**
     * 检测点是否在矩形内
     * @param x 点的X坐标
     * @param y 点的Y坐标
     * @param rect 矩形
     * @return 是否在矩形内
     */
    public static boolean isPointInRect(float x, float y, Rect rect) {
        return x >= rect.left && x <= rect.right && 
               y >= rect.top && y <= rect.bottom;
    }
    
    /**
     * 获取两个矩形的重叠区域
     * @param rect1 矩形1
     * @param rect2 矩形2
     * @return 重叠区域，如果没有重叠返回null
     */
    public static Rect getOverlapRect(Rect rect1, Rect rect2) {
        if (!checkRectCollision(rect1, rect2)) {
            return null;
        }
        
        int left = Math.max(rect1.left, rect2.left);
        int top = Math.max(rect1.top, rect2.top);
        int right = Math.min(rect1.right, rect2.right);
        int bottom = Math.min(rect1.bottom, rect2.bottom);
        
        return new Rect(left, top, right, bottom);
    }
    
    /**
     * 计算两个点之间的距离
     * @param x1 点1的X坐标
     * @param y1 点1的Y坐标
     * @param x2 点2的X坐标
     * @param y2 点2的Y坐标
     * @return 两点间距离
     */
    public static float getDistance(float x1, float y1, float x2, float y2) {
        float dx = x2 - x1;
        float dy = y2 - y1;
        return (float) Math.sqrt(dx * dx + dy * dy);
    }
    
    /**
     * 检测圆形碰撞 (备用方法，可用于特殊形状的碰撞检测)
     * @param x1 圆心1的X坐标
     * @param y1 圆心1的Y坐标
     * @param radius1 圆1的半径
     * @param x2 圆心2的X坐标
     * @param y2 圆心2的Y坐标
     * @param radius2 圆2的半径
     * @return 是否发生碰撞
     */
    public static boolean checkCircleCollision(float x1, float y1, float radius1,
                                               float x2, float y2, float radius2) {
        float distance = getDistance(x1, y1, x2, y2);
        return distance <= (radius1 + radius2);
    }
    
    /**
     * 检测玩家是否处于安全区域（用于特殊游戏机制）
     * @param player 玩家对象
     * @param safeZone 安全区域矩形
     * @return 是否在安全区域内
     */
    public static boolean isPlayerInSafeZone(Player player, Rect safeZone) {
        Rect playerRect = player.getCollisionRect();
        return safeZone.contains(playerRect);
    }
    
    /**
     * 获取碰撞边距设置
     * @return 当前碰撞边距
     */
    public static int getCollisionMargin() {
        return COLLISION_MARGIN;
    }
    
    // ========== 道具系统碰撞检测 ==========
    
    /**
     * 检测玩家与道具的碰撞
     * @param player 玩家对象
     * @param powerUp 道具对象
     * @return 是否发生碰撞
     */
    public static boolean checkPlayerPowerUpCollision(Player player, PowerUp powerUp) {
        if (powerUp.isCollected()) {
            return false;
        }
        
        Rect playerRect = player.getCollisionRect();
        Rect powerUpRect = powerUp.getCollisionRect();
        
        // 道具收集使用更宽松的碰撞检测，方便玩家收集
        return checkRectCollision(playerRect, powerUpRect);
    }
    
    /**
     * 检测玩家与多个道具的碰撞
     * @param player 玩家对象
     * @param powerUps 道具列表
     * @return 发生碰撞的道具，如果没有碰撞返回null
     */
    public static PowerUp checkPlayerPowerUpsCollision(Player player, ArrayList<PowerUp> powerUps) {
        for (PowerUp powerUp : powerUps) {
            if (checkPlayerPowerUpCollision(player, powerUp)) {
                return powerUp;
            }
        }
        return null;
    }
    
    /**
     * 检测道具是否与障碍物重叠（防止道具生成在障碍物内）
     * @param powerUp 道具对象
     * @param blocks 障碍物列表
     * @return 是否与障碍物重叠
     */
    public static boolean checkPowerUpBlockOverlap(PowerUp powerUp, ArrayList<Block> blocks) {
        Rect powerUpRect = powerUp.getCollisionRect();
        
        for (Block block : blocks) {
            Rect blockRect = block.getCollisionRect();
            if (checkRectCollision(powerUpRect, blockRect)) {
                return true;
            }
        }
        return false;
    }
    
    // === 新障碍物类型碰撞检测方法 ===
    
    /**
     * 检测玩家与抽象障碍物的碰撞（支持所有障碍物类型）
     * @param player 玩家对象
     * @param obstacle 抽象障碍物
     * @return 是否发生碰撞
     */
    public static boolean checkPlayerObstacleCollision(Player player, AbstractObstacle obstacle) {
        if (!obstacle.isActive()) return false;
        
        Rect playerRect = player.getCollisionRect();
        Rect obstacleRect = obstacle.getCollisionRect();
        
        return checkPreciseCollision(playerRect, obstacleRect);
    }
    
    /**
     * 检测玩家是否越过抽象障碍物
     * @param player 玩家对象
     * @param obstacle 抽象障碍物
     * @return 是否成功越过
     */
    public static boolean checkPlayerPassedObstacle(Player player, AbstractObstacle obstacle) {
        if (obstacle.isPassed()) return false;
        
        // 玩家的左边缘是否已经超过障碍物的右边缘
        float playerLeftEdge = player.getX();
        float obstacleRightEdge = obstacle.getRightEdge();
        
        return playerLeftEdge > obstacleRightEdge;
    }
    
    /**
     * 精确碰撞检测（带容错边距）- 重载版本
     * @param rect1 矩形1
     * @param rect2 矩形2
     * @return 是否发生碰撞
     */
    private static boolean checkPreciseCollision(Rect rect1, Rect rect2) {
        // 应用容错边距
        Rect adjustedRect1 = new Rect(
            rect1.left + COLLISION_MARGIN,
            rect1.top + COLLISION_MARGIN,
            rect1.right - COLLISION_MARGIN,
            rect1.bottom - COLLISION_MARGIN
        );
        
        return checkRectCollision(adjustedRect1, rect2);
    }
    
    /**
     * 检测道具是否与抽象障碍物重叠
     * @param powerUp 道具对象
     * @param obstacles 障碍物列表
     * @return 是否与障碍物重叠
     */
    public static boolean checkPowerUpObstacleOverlap(PowerUp powerUp, java.util.List<AbstractObstacle> obstacles) {
        Rect powerUpRect = powerUp.getCollisionRect();
        
        for (AbstractObstacle obstacle : obstacles) {
            if (obstacle.isActive()) {
                Rect obstacleRect = obstacle.getCollisionRect();
                if (checkRectCollision(powerUpRect, obstacleRect)) {
                    return true;
                }
            }
        }
        return false;
    }
    
    /**
     * 高级碰撞检测 - 支持障碍物特殊形状和多部分检测
     * @param player 玩家对象
     * @param obstacle 障碍物对象
     * @return 碰撞详情
     */
    public static CollisionResult checkAdvancedCollision(Player player, AbstractObstacle obstacle) {
        CollisionResult result = new CollisionResult();
        result.hasCollision = false;
        result.obstacle = obstacle;
        result.collisionPoint = new android.graphics.PointF();
        
        if (!obstacle.isActive()) return result;
        
        // 基础碰撞检测
        if (checkPlayerObstacleCollision(player, obstacle)) {
            result.hasCollision = true;
            
            // 计算碰撞点
            Rect playerRect = player.getCollisionRect();
            Rect obstacleRect = obstacle.getCollisionRect();
            
            result.collisionPoint.x = Math.max(playerRect.left, obstacleRect.left);
            result.collisionPoint.y = Math.max(playerRect.top, obstacleRect.top);
            
            // 判断碰撞类型
            if (playerRect.bottom <= obstacleRect.top + 10) {
                result.collisionSide = CollisionResult.CollisionSide.TOP;
            } else if (playerRect.top >= obstacleRect.bottom - 10) {
                result.collisionSide = CollisionResult.CollisionSide.BOTTOM;
            } else if (playerRect.right <= obstacleRect.left + 10) {
                result.collisionSide = CollisionResult.CollisionSide.LEFT;
            } else {
                result.collisionSide = CollisionResult.CollisionSide.RIGHT;
            }
        }
        
        return result;
    }
    
    /**
     * 碰撞结果类 - 提供详细的碰撞信息
     */
    public static class CollisionResult {
        public boolean hasCollision;
        public AbstractObstacle obstacle;
        public android.graphics.PointF collisionPoint;
        public CollisionSide collisionSide;
        
        public enum CollisionSide {
            TOP, BOTTOM, LEFT, RIGHT, UNKNOWN
        }
    }
}